package control

import (
	"jvm/nzpJvm/instructions/base"
	"jvm/nzpJvm/runtime_area"
)

// 方法返回指令
// 无返回值
type RETURN struct {base.NoOperandsInstruction}
// 返回一个对象引用
type ARETURN struct {base.NoOperandsInstruction}
// 返回一个double值
type DRETURN struct {base.NoOperandsInstruction}
// 返回一个float值
type FRETURN struct {base.NoOperandsInstruction}
// 返回一个int值。byte、short等返回也是用这个指令
type IRETURN struct {base.NoOperandsInstruction}
// 返回一个long值
type LRETURN struct {base.NoOperandsInstruction}

func (self *RETURN) Execute(frame *runtime_area.Frame) {
	frame.Thread().PopFrame()
}

func (self *ARETURN) Execute(frame *runtime_area.Frame) {
	thread := frame.Thread()
	// 当前栈帧
	currentFrame := thread.PopFrame()
	// 调用者栈帧
	invokerFrame := thread.CurrentFrame()
	// 需要返回的值从当前栈帧中弹出
	value := currentFrame.OperandStack().PopRef()
	// 需要返回的值压入调用者栈帧中
	invokerFrame.OperandStack().PushRef(value)
}

func (self *DRETURN) Execute(frame *runtime_area.Frame) {
	thread := frame.Thread()
	// 当前栈帧
	currentFrame := thread.PopFrame()
	// 调用者栈帧
	invokerFrame := thread.CurrentFrame()
	// 需要返回的值从当前栈帧中弹出
	value := currentFrame.OperandStack().PopDouble()
	// 需要返回的值压入调用者栈帧中
	invokerFrame.OperandStack().PushDouble(value)
}

func (self *FRETURN) Execute(frame *runtime_area.Frame) {
	thread := frame.Thread()
	// 当前栈帧
	currentFrame := thread.PopFrame()
	// 调用者栈帧
	invokerFrame := thread.CurrentFrame()
	// 需要返回的值从当前栈帧中弹出
	value := currentFrame.OperandStack().PopFloat()
	// 需要返回的值压入调用者栈帧中
	invokerFrame.OperandStack().PushFloat(value)
}

func (self *IRETURN) Execute(frame *runtime_area.Frame) {
	thread := frame.Thread()
	// 当前栈帧
	currentFrame := thread.PopFrame()
	// 调用者栈帧
	invokerFrame := thread.CurrentFrame()
	// 需要返回的值从当前栈帧中弹出
	value := currentFrame.OperandStack().PopInt()
	// 需要返回的值压入调用者栈帧中
	invokerFrame.OperandStack().PushInt(value)
}

func (self *LRETURN) Execute(frame *runtime_area.Frame) {
	thread := frame.Thread()
	// 当前栈帧
	currentFrame := thread.PopFrame()
	// 调用者栈帧
	invokerFrame := thread.CurrentFrame()
	// 需要返回的值从当前栈帧中弹出
	value := currentFrame.OperandStack().PopLong()
	// 需要返回的值压入调用者栈帧中
	invokerFrame.OperandStack().PushLong(value)
}